﻿#include "FITKAdaptorGeoDatumModel.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoDatum.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoReferencePoint.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoReferenceLine.h"
#include "FITK_Interface/FITKInterfaceGeometry/FITKAbsGeoReferencePlane.h"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Writer.h"
#include "FITK_Interface/FITKInterfaceIO/FITKAbstractHDF5Reader.h"
#include "FITK_Interface/FITKInterfaceIO/FITKHDF5FileTool.h"
#include <QMetaEnum>

namespace Interface
{
    bool  FITKAdaptorGeoDatumPoint::readParameters()
    {
        Interface::FITKAbsGeoDatum* cmd = this->getDataObjectAs<Interface::FITKAbsGeoDatum>();
        
        if (cmd == nullptr || _reader == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _reader->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = { };
        
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position, position, 1, 3)) return false;
        cmd->setPosition(position);
        if (cmd->getDatumType() == Interface::FITKGeoEnum::FITKDatumType::FDTPoint)
        {
            return true;
        }
        else
        {
            Interface::FITKAbsGeoDatumLine* datum = dynamic_cast<Interface::FITKAbsGeoDatumLine*>(cmd);
            if (datum == nullptr) return false;
            double pos1[3] = {};
            double pos2[3] = {};
            if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position1, pos1, 1, 3)) return false;
            if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position2, pos2, 1, 3)) return false;
            datum->setFiniteLine(pos1, pos2);
            return true;
        }
        
    }
    bool FITKAdaptorGeoDatumPoint::writeParameters(H5::Group &g)
    {
        Interface::FITKAbsGeoDatum* cmd = this->getDataObjectAs<Interface::FITKAbsGeoDatum>();
        if (cmd == nullptr || _writer == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _writer->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = {};
        cmd->getPosition(position);
        Interface::FITKGeoEnum::FITKDatumType t = cmd->getDatumType();

        //Object Type
        QMetaEnum metaEnum = QMetaEnum::fromType<Interface::FITKGeoEnum::FITKDatumType>();
        std::string strDatumType = metaEnum.valueToKey(t);
        if (strDatumType.empty()) return false;
        h5tools->writeGroupAttrStr(g, FGKW_Type, strDatumType);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position, position, 1, 3);
        //写出参数
        if (t == Interface::FITKGeoEnum::FITKDatumType::FDTPoint)
        {
            return true;
        }
        else
        {
            Interface::FITKAbsGeoDatumLine* datum = dynamic_cast<Interface::FITKAbsGeoDatumLine*>(cmd);
            if (datum == nullptr) return false;
            double pos1[3] = {};
            double pos2[3] = {};
            datum->getFiniteLine(pos1, pos2);
            h5tools->writeGroupAttrDoubleArray(g, FGKW_Position1, pos1, 1, 3);
            h5tools->writeGroupAttrDoubleArray(g, FGKW_Position2, pos2, 1, 3);
            return true;
        }
    }
    bool  FITKAdaptorGeoDatumLine::readParameters()
    {
        /*Interface::FITKAbsGeoDatum* datum = this->getDataObjectAs<Interface::FITKAbsGeoDatum>();
        if (datum == nullptr) return false;
        Interface::FITKAbsGeoDatumLine* cmd = dynamic_cast<Interface::FITKAbsGeoDatumLine*>(datum);
        if (cmd == nullptr || _reader == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _reader->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = { };
        double pos1[3] = {};
        double pos2[3] = {};

        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position, position, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position1, pos1, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, "Position2", pos2, 1, 3)) return false;

        cmd->setPosition(position);
        cmd->setFiniteLine(pos1, pos2);*/
        return true;
    }
    bool FITKAdaptorGeoDatumLine::writeParameters(H5::Group &g)
    {
        //Interface::FITKAbsGeoDatum* datum = this->getDataObjectAs<Interface::FITKAbsGeoDatum>();
        //if (datum == nullptr) return false;
        //Interface::FITKAbsGeoDatumLine* cmd = dynamic_cast<Interface::FITKAbsGeoDatumLine*>(datum);
        //if (cmd == nullptr || _writer == nullptr || _h5Group == nullptr) return false;
        //IO::FITKHDF5FileTool* h5tools = _writer->getHDF5FileTool();
        //if (h5tools == nullptr) return false;

        //double position[3] = {};
        //double pos1[3] = {};
        //double pos2[3] = {};
        //cmd->getPosition(position);
        //cmd->getFiniteLine(pos1, pos2);
        //Interface::FITKGeoEnum::FITKDatumType t = cmd->getDatumType();

        ////Object Type
        //QMetaEnum metaEnum = QMetaEnum::fromType<Interface::FITKGeoEnum::FITKDatumType>();
        //std::string strDatumType = metaEnum.valueToKey(t);
        //if (strDatumType.empty()) return false;
        ////写出参数
        //h5tools->writeGroupAttrDoubleArray(g, FGKW_Position, position, 1, 3);
        //h5tools->writeGroupAttrDoubleArray(g, FGKW_Position1, pos1, 1, 3);
        //h5tools->writeGroupAttrDoubleArray(g, "Position2", pos2, 1, 3);
        //h5tools->writeGroupAttrStr(g, FGKW_Type, strDatumType);

        return true;
    }

    bool  FITKAdaptorGeoDatumPlane::readParameters()
    {
        Interface::FITKAbsGeoDatumPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoDatumPlane>();
        if (cmd == nullptr || _reader == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _reader->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = { };
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};

        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position, position, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position1, pos, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Normal, normal, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Up, up, 1, 3)) return false;

        cmd->setPosition(position);
        cmd->setPlane(pos, normal, up);

        return true;
    }
    bool FITKAdaptorGeoDatumPlane::writeParameters(H5::Group &g)
    {
        Interface::FITKAbsGeoDatumPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoDatumPlane>();
        if (cmd == nullptr || _writer == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _writer->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = {};
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};
        cmd->getPosition(position);
        cmd->getPlane(pos, normal, up);
        Interface::FITKGeoEnum::FITKDatumType t = cmd->getDatumType();

        //Object Type
        QMetaEnum metaEnum = QMetaEnum::fromType<Interface::FITKGeoEnum::FITKDatumType>();
        std::string strDatumType = metaEnum.valueToKey(t);
        if (strDatumType.empty()) return false;
        //写出参数
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position, position, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position1, pos, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Normal, normal, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Up, up, 1, 3);
        h5tools->writeGroupAttrStr(g, FGKW_Type, strDatumType);

        return true;
    }

    bool  FITKAdaptorGeoReferenceOffsetPlane::readParameters()
    {
        Interface::FITKAbsGeoReferenceOffsetPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoReferenceOffsetPlane>();
        if (cmd == nullptr || _reader == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _reader->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = {};
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};
        int cmdId = 0;
        int virtualTopoId = 0;
        int virtualTopoIndex = 0;
        double offset = 0;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position, position, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position1, pos, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Normal, normal, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Up, up, 1, 3)) return false;
        if (!h5tools->readGroupint(*_h5Group, FGKW_cmdID, &cmdId)) return false;
        if (!h5tools->readGroupint(*_h5Group, FGKW_vTopoID, &virtualTopoId)) return false;
        if (!h5tools->readGroupint(*_h5Group, FGKW_vTopoIndex, &virtualTopoIndex)) return false;
        if (!h5tools->readGroupDouble(*_h5Group, FGKW_Offset, &offset)) return false;

        cmd->setPosition(position[0], position[1], position[2]);
        cmd->setPlane(pos, normal, up);
        Interface::VirtualShape sObject(cmdId, virtualTopoId, virtualTopoIndex);
        cmd->setSourceSurface(sObject);
        cmd->setOffset(offset);

        return true;
    }
    bool FITKAdaptorGeoReferenceOffsetPlane::writeParameters(H5::Group &g)
    {
        Interface::FITKAbsGeoReferenceOffsetPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoReferenceOffsetPlane>();
        if (cmd == nullptr || _writer == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _writer->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = {};
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};
        cmd->getPosition(position);
        cmd->getPlane(pos, normal, up);
        Interface::VirtualShape sObject = cmd->sourceSurface();
        int cmdId = sObject.CmdId;
        int virtualTopoId = sObject.VirtualTopoId;
        int virtualTopoIndex = sObject.VirtualTopoIndex;
        double offset = cmd->offset();
        Interface::FITKGeoEnum::FITKDatumType t = cmd->getDatumType();

        //Object Type
        QMetaEnum metaEnum = QMetaEnum::fromType<Interface::FITKGeoEnum::FITKDatumType>();
        std::string strDatumType = metaEnum.valueToKey(t);
        if (strDatumType.empty()) return false;
        //写出参数
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position, position, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position1, pos, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Normal, normal, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Up, up, 1, 3);
        h5tools->writeGroupAttrInt(g, FGKW_cmdID, cmdId);
        h5tools->writeGroupAttrInt(g, FGKW_vTopoID, virtualTopoId);
        h5tools->writeGroupAttrInt(g, FGKW_vTopoIndex, virtualTopoIndex);
        h5tools->writeGroupAttrDouble(g, FGKW_Offset, offset);
        h5tools->writeGroupAttrStr(g, FGKW_Type, strDatumType);

        return true;
    }

    bool  FITKAdaptorGeoReferenceThreePointsPlane::readParameters()
    {
        Interface::FITKAbsGeoReferenceThreePointsPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoReferenceThreePointsPlane>();
        if (cmd == nullptr || _reader == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _reader->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = { };
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};

        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position, position, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position1, pos, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Normal, normal, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Up, up, 1, 3)) return false;
        for (int i = 0; i < 3; i++)
        {
            double P_i[3] = {};
            if (!h5tools->readGroupAttrDoubleArray(*_h5Group, std::to_string(i).c_str(), P_i, 1, 3)) return false;
            cmd->setPoint(i, P_i[0], P_i[1], P_i[2]);
        }
        cmd->setPosition(position[0], position[1], position[2]);
        cmd->setPlane(pos, normal, up);

        return true;
    }
    bool FITKAdaptorGeoReferenceThreePointsPlane::writeParameters(H5::Group &g)
    {
        Interface::FITKAbsGeoReferenceThreePointsPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoReferenceThreePointsPlane>();
        if (cmd == nullptr || _writer == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _writer->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = {};
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};
        cmd->getPosition(position);
        cmd->getPlane(pos, normal, up);
        Interface::FITKGeoEnum::FITKDatumType t = cmd->getDatumType();

        //Object Type
        QMetaEnum metaEnum = QMetaEnum::fromType<Interface::FITKGeoEnum::FITKDatumType>();
        std::string strDatumType = metaEnum.valueToKey(t);
        if (strDatumType.empty()) return false;
        //写出参数
        for (int i = 0; i < 3; i++)
        {
            std::array<double, 3> point = cmd->point(i);
            double P_i[3]{ point[0],point[1],point[2] };
            h5tools->writeGroupAttrDoubleArray(g, std::to_string(i).c_str(), P_i, 1, 3);
        }
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position, position, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position1, pos, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Normal, normal, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Up, up, 1, 3);
        h5tools->writeGroupAttrStr(g, FGKW_Type, strDatumType);

        return true;
    }

    bool  FITKAdaptorGeoReferenceEquationPlane::readParameters()
    {
        Interface::FITKAbsGeoReferenceEquationPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoReferenceEquationPlane>();
        if (cmd == nullptr || _reader == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _reader->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = { };
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};
        double a = {};
        double b = {};
        double c = {};
        double d = {};
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position, position, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position1, pos, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Normal, normal, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Up, up, 1, 3)) return false;
        if (!h5tools->readGroupDouble(*_h5Group, FGKW_A, &a)) return false;
        if (!h5tools->readGroupDouble(*_h5Group, FGKW_B, &b)) return false;
        if (!h5tools->readGroupDouble(*_h5Group, FGKW_C, &c)) return false;
        if (!h5tools->readGroupDouble(*_h5Group, FGKW_D, &d)) return false;

        cmd->setPosition(position[0], position[1], position[2]);
        cmd->setPlane(pos, normal, up);
        cmd->setA(a);
        cmd->setB(b);
        cmd->setC(c);
        cmd->setD(d);
        return true;
    }
    bool FITKAdaptorGeoReferenceEquationPlane::writeParameters(H5::Group &g)
    {
        Interface::FITKAbsGeoReferenceEquationPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoReferenceEquationPlane>();
        if (cmd == nullptr || _writer == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _writer->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = {};
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};
        cmd->getPosition(position);
        cmd->getPlane(pos, normal, up);
        double a = cmd->a();
        double b = cmd->b();
        double c = cmd->c();
        double d = cmd->d();
        Interface::FITKGeoEnum::FITKDatumType t = cmd->getDatumType();

        //Object Type
        QMetaEnum metaEnum = QMetaEnum::fromType<Interface::FITKGeoEnum::FITKDatumType>();
        std::string strDatumType = metaEnum.valueToKey(t);
        if (strDatumType.empty()) return false;
        //写出参数
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position, position, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position1, pos, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Normal, normal, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Up, up, 1, 3);
        h5tools->writeGroupAttrDouble(g, FGKW_A, a);
        h5tools->writeGroupAttrDouble(g, FGKW_B, b);
        h5tools->writeGroupAttrDouble(g, FGKW_C, c);
        h5tools->writeGroupAttrDouble(g, FGKW_D, d);
        h5tools->writeGroupAttrStr(g, FGKW_Type, strDatumType);

        return true;
    }

    bool  FITKAdaptorGeoReferencePointAndDirectionPlane::readParameters()
    {
        Interface::FITKAbsGeoReferencePointAndDirectionPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoReferencePointAndDirectionPlane>();
        if (cmd == nullptr || _reader == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _reader->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = { };
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};
        double point[3] = {};
        double direction[3] = {};

        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position, position, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Position1, pos, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Normal, normal, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Up, up, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Point, point, 1, 3)) return false;
        if (!h5tools->readGroupAttrDoubleArray(*_h5Group, FGKW_Direction, direction, 1, 3)) return false;

        cmd->setPosition(position[0], position[1], position[2]);
        cmd->setPlane(pos, normal, up);
        cmd->setPoint(point[0], point[1], point[2]);
        cmd->setDirection(direction[0], direction[1], direction[2]);

        return true;
    }
    bool FITKAdaptorGeoReferencePointAndDirectionPlane::writeParameters(H5::Group &g)
    {
        Interface::FITKAbsGeoReferencePointAndDirectionPlane* cmd = this->getDataObjectAs<Interface::FITKAbsGeoReferencePointAndDirectionPlane>();
        if (cmd == nullptr || _writer == nullptr || _h5Group == nullptr) return false;
        IO::FITKHDF5FileTool* h5tools = _writer->getHDF5FileTool();
        if (h5tools == nullptr) return false;

        double position[3] = {};
        double pos[3] = {};
        double normal[3] = {};
        double up[3] = {};
        cmd->getPosition(position);
        cmd->getPlane(pos, normal, up);
        std::array<double, 3> point = cmd->point();
        std::array<double, 3> direction = cmd->direction();
        
        Interface::FITKGeoEnum::FITKDatumType t = cmd->getDatumType();

        //Object Type
        QMetaEnum metaEnum = QMetaEnum::fromType<Interface::FITKGeoEnum::FITKDatumType>();
        std::string strDatumType = metaEnum.valueToKey(t);
        if (strDatumType.empty()) return false;
        //写出参数
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position, position, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Position1, pos, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Normal, normal, 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Up, up, 1, 3);
        h5tools->writeGroupAttrStr(g, FGKW_Type, strDatumType);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Point, point.data(), 1, 3);
        h5tools->writeGroupAttrDoubleArray(g, FGKW_Direction, direction.data(), 1, 3);

        return true;
    }

}
